
// -----------------------------------------------------------------------------

#ifdef _CONSOLE
#include <TCHAR.h>
#endif

#include "stdafx.h"
#include "Win32.Diagnostics.Log.h"
#include "Win32.DateTime.h"
#include "Win32.Xml.XmlWriter.h"
#include "Win32.IO.TextFile.h"
#include "Win32.Number.h"

namespace Xml = Kif::Win32::Xml;
namespace Base = Kif::Win32;

namespace Kif
{
namespace Win32
{
namespace Diagnostics
{

// -----------------------------------------------------------------------------

/// <summary>output given message as an Xml Log Entry.
/// note that the Caller is responsable for the disposition
/// of the string</summary>
Kif::Win32::String *LogMessages::ToXmlString()
{
   TCHAR entryTag[] = _T("ResultsLog");
   Kif::Win32::String *mess;
   int  messCount = 0;
   bool inited = false;
   if (!Open())
      return(NULL);
   Kif::Win32::String *outStr = new Kif::Win32::String();
   while(Read())
   {
      if (!inited) 
      {
         Xml::XmlWriter::WriteStartTag(entryTag,SizeOf(entryTag),outStr);
         inited = true;
      }

      if (Item.Severity != Severity_Unknown)
      {
         mess = Item.ToXmlString();
         if (mess != NULL)
         {
            outStr->Concat(mess);
            delete mess;
            messCount++;
         }
         if (Item.XmlAppendix.GetLength() > 0)
            outStr->Concat(Item.XmlAppendix);
      }
   }

   if (messCount > 0)
      Xml::XmlWriter::WriteEndTag(entryTag,SizeOf(entryTag),outStr);
   return(outStr);
}  // end of ToXmlString

// -----------------------------------------------------------------------------

/// <summary>output given message as an Xml Log Entry.
/// note that the Caller is responsable for the disposition
/// of the string</summary>
Kif::Win32::String *Log::ToXmlLogEntry(
   TCHAR *location, TCHAR *message, SeverityLevel severity)
{
   Base::String *severityString = GetSeverityString(severity);

   TCHAR entryTag[]    = _T("Entry");
   TCHAR messageTag[]  = _T("Message");
   TCHAR locationTag[] = _T("Location");
   TCHAR severityTag[] = _T("Severity");
   TCHAR dateTag[]     = _T("Date");

   // make sure that there is something to write
   if ((message == NULL) && (location == NULL) && (severityString == NULL))
      return(NULL);

   // first build message
   Base::String *outMess = new Base::String();
   Xml::XmlWriter::WriteStartTag(entryTag,SizeOf(entryTag),outMess);

   // write date
   Xml::XmlWriter::WriteDate(outMess);

   // write message
   if (message != NULL)
   Xml::XmlWriter::WriteElement(
      messageTag,SizeOf(messageTag),
      message,Base::String::GetLength(message),outMess);

   // write location
   if (location != NULL)
      Xml::XmlWriter::WriteElement(
         locationTag,SizeOf(locationTag),
         location,Base::String::GetLength(location),outMess);

   // write severity
   if ((severity != Severity_None) && (severityString != NULL))
      Xml::XmlWriter::WriteElement(
         severityTag,SizeOf(severityTag),
         severityString,outMess);

   // close entry
   Xml::XmlWriter::WriteEndTag(entryTag,SizeOf(entryTag),outMess);

   delete severityString;
   return(outMess);
}  // end of ToXmlLogEntry

/// <summary>output given message using given log path file name</summary>
void Log::WriteLogFile(TCHAR *logPath, Kif::Win32::String &message)
{
   Kif::Win32::IO::TextFile tf;
   tf.OpenReadWrite(logPath);
   tf.WriteLine(&message);
   tf.Close();
}  // end of WriteLogFile

/// <summary>output given message to default device</summary>
void Log::WriteMessage(
   TCHAR *logPath, TCHAR *location, TCHAR *message, SeverityLevel severity,
   LogOutputOption outputTo)
{
   if (message == NULL)
      return;

   // output to console (if possible)
   if ((outputTo == LogTo_ConsoleOnly) ||
       (outputTo == LogTo_ConsoleAndErrorLog))
   {
      #ifdef _CONSOLE
      _tprintf(L"%s\n",message);
      #endif
   }

   // output to log file (if available)
   if (((outputTo == LogTo_ErrorLogOnly) ||
        (outputTo == LogTo_ConsoleAndErrorLog)) && (logPath != NULL)
      )
   {
      TCHAR fileExt[] = _T(".log");
      Base::String *e = ToXmlLogEntry(location,message,severity);
      if (e == NULL)
         return;

      // prepare output file full path
      Base::String *f = Kif::Win32::DateTime::GetYmdString(
         Kif::Win32::DateTime::MinYmdStringLength,0);

      Base::String path;
      path.Copy(logPath);
      f->Concat(fileExt,SizeOf(fileExt));
      path.Concat(f);
      delete f;

      // write message to file
      WriteLogFile(path.GetBuffer(), *e);

      delete e;
   }

}  // end of WriteMessage

/// <summary>output given message to default device</summary>
void Log::WriteMessageToFile(
   TCHAR *logPath, TCHAR *location, TCHAR *message, SeverityLevel severity,
   LogOutputOption outputTo)
{
   if (message == NULL)
      return;

   // output to console (if possible)
   if ((outputTo == LogTo_ConsoleOnly) ||
       (outputTo == LogTo_ConsoleAndErrorLog))
   {
      #ifdef _CONSOLE
      _tprintf(L"%s\n",message);
      #endif
   }

   // output to log file (if available)
   if (((outputTo == LogTo_ErrorLogOnly) ||
        (outputTo == LogTo_ConsoleAndErrorLog)) && (logPath != NULL)
      )
   {
      TCHAR fileExt[] = _T(".log");
      Base::String *e = ToXmlLogEntry(location,message,severity);

      // prepare output file full path
      Base::String path;
      path.Copy(logPath);

      // write message to file
      Kif::Win32::IO::TextFile tf;
      tf.OpenReadWrite(path.GetBuffer());
      tf.WriteLine(e);
      tf.Close();
      delete e;
   }
}  // end of WriteMessage

/// <summary>output given fail operation error message to default device</summary>
void Log::WriteMessage(
   TCHAR *logPath, TCHAR *location, TCHAR *operation, TCHAR *message,
   SeverityLevel severity, LogOutputOption outputTo)
{
   TCHAR rmMess1[] = _T("Failed to ");
   TCHAR rmMess2[] = _T(" (\"");
   TCHAR rmMess3[] = _T("\").");

   Base::String errMess;
   errMess.Copy(rmMess1,SizeOf(rmMess1));
   errMess.Concat(operation,Base::String::GetLength(operation));
   errMess.Concat(rmMess2,SizeOf(rmMess2));
   errMess.Concat(message,Base::String::GetLength(message));
   errMess.Concat(rmMess3,SizeOf(rmMess3));

   WriteMessage(
      logPath, location, errMess.GetBuffer(),
      Kif::Win32::Diagnostics::Severity_Warning,
      Kif::Win32::Diagnostics::LogTo_ConsoleAndErrorLog);
}  // end of WriteErrorMessage

void Log::WriteMessage(TCHAR *location, TCHAR *message, HRESULT hResult)
{
   TCHAR rmMess1[] = _T(" (");
   TCHAR rmMess2[] = _T(")");

   Base::String errMess;
   Base::String hexHResult;
   Kif::Win32::Number::ToHexString(hexHResult,hResult);

   errMess.Copy(message,Base::String::GetLength(message));
   errMess.Copy(rmMess1,SizeOf(rmMess1));
   errMess.Concat(hexHResult);
   errMess.Concat(rmMess2,SizeOf(rmMess2));

   Kif::Win32::Diagnostics::SeverityLevel slevel =
      hResult == 0 ? Kif::Win32::Diagnostics::Severity_Warning :
         Kif::Win32::Diagnostics::Severity_Fatal;

   WriteMessage(
      NULL, location, errMess.GetBuffer(), slevel,
      Kif::Win32::Diagnostics::LogTo_ConsoleAndErrorLog);
}  // end of WriteMessage

}  // end of Kif::Win32::Diagnostics
}  // end of Kif::Win32
}  // end of Kif

